package com.enation.app.javashop.consumer.shop.goods;

import com.alibaba.fastjson.JSON;
import com.enation.app.javashop.consumer.core.event.OrderStatusChangeEvent;
import com.enation.app.javashop.consumer.core.event.RefundStatusChangeEvent;
import com.enation.app.javashop.core.aftersale.model.dos.RefundDO;
import com.enation.app.javashop.core.aftersale.model.dos.RefundGoodsDO;
import com.enation.app.javashop.core.aftersale.model.enums.RefundStatusEnum;
import com.enation.app.javashop.core.aftersale.model.enums.RefuseTypeEnum;
import com.enation.app.javashop.core.base.message.OrderStatusChangeMsg;
import com.enation.app.javashop.core.base.message.RefundChangeMsg;
import com.enation.app.javashop.core.client.goods.GoodsQuantityClient;
import com.enation.app.javashop.core.client.trade.AfterSaleClient;
import com.enation.app.javashop.core.client.trade.OrderClient;
import com.enation.app.javashop.core.goods.model.enums.QuantityType;
import com.enation.app.javashop.core.goods.model.vo.GoodsQuantityVO;
import com.enation.app.javashop.core.goods.service.GoodsStockManager;
import com.enation.app.javashop.core.trade.cart.model.vo.CartSkuVO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderItemsDO;
import com.enation.app.javashop.core.trade.order.model.dto.OrderDTO;
import com.enation.app.javashop.core.trade.order.model.enums.OrderOperateEnum;
import com.enation.app.javashop.core.trade.order.model.enums.OrderStatusEnum;
import com.enation.app.javashop.core.trade.order.model.enums.PayStatusEnum;
import com.enation.app.javashop.core.trade.order.model.enums.ShipStatusEnum;
import com.enation.app.javashop.core.trade.order.model.vo.OrderSkuVO;
import com.enation.app.javashop.core.trade.order.service.OrderQueryManager;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.framework.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 商品库存增加/扣减
 *
 * @author fk
 * @version v1.0
 * @since v7.0.0
 * 2018年6月22日 上午10:18:20
 */
@Service
public class GoodsQuantityChangeConsumer implements OrderStatusChangeEvent, RefundStatusChangeEvent {

    @Autowired
    private GoodsQuantityClient goodsQuantityClient;

    @Autowired
    private AfterSaleClient afterSaleClient;

    @Autowired
    private OrderClient orderClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private OrderQueryManager orderQueryManager;

    @Autowired
    private GoodsStockManager goodsStockManager;

    /**
     * 订单变化处理
     *
     * @param orderMessage 订单变化消息
     */
    @Override
    public void orderChange(OrderStatusChangeMsg orderMessage) {
        // 订单新状态为已发货 且 订单旧状态为已支付，是订单中商品全部发货，更新库存要更新订单中全部商品的库存
        if (orderMessage.getNewStatus().name().equals(OrderStatusEnum.SHIPPED.name())
                && orderMessage.getOldStatus().name().equals(OrderStatusEnum.PAID_OFF.name()) ) {

            // 1.获取订单sku信息
            OrderDO order = orderMessage.getOrderDO();
            String itemsJson = order.getItemsJson();
            List<OrderSkuVO> list = JsonUtil.jsonToList(itemsJson, OrderSkuVO.class);

            // 2.构建扣减商品库存VO
            List<GoodsQuantityVO> quantityVOList = new ArrayList<>();
            for (OrderSkuVO sku : list) {
                GoodsQuantityVO goodsQuantity = new GoodsQuantityVO();
                goodsQuantity.setGoodsId(sku.getGoodsId());
                //设置为要减掉的库存
                goodsQuantity.setQuantity(0 - sku.getNum());
                //发货要减少实际的库存
                goodsQuantity.setQuantityType(QuantityType.actual);
                goodsQuantity.setSkuId(sku.getSkuId());
                quantityVOList.add(goodsQuantity);
            }
            // 3.扣减库存
            goodsQuantityClient.updateSkuQuantity(quantityVOList);

        }

        // 订单新状态为部分发货 和 已发货且订单旧状态为部分发货，是订单分包裹发货，更新库存只更新部分发货商品的库存
        if (orderMessage.getNewStatus().name().equals(OrderStatusEnum.PART_SHIPPED.name())
                || (orderMessage.getNewStatus().name().equals(OrderStatusEnum.SHIPPED.name())
                && orderMessage.getOldStatus().name().equals(OrderStatusEnum.PART_SHIPPED.name()))) {

            // 1.从redis中获取部分发货的商品IDs
            OrderDO order = orderMessage.getOrderDO();
            String key = OrderOperateEnum.SPLIT_SHIP.name() + "_" + order.getSn();
            String skuIdsString = stringRedisTemplate.opsForValue().get(key);

            // 2.根据orderSn和goodsIds查询orderItem集合
            List<OrderItemsDO> orderItems = orderQueryManager.getOrderItems(order.getSn(), skuIdsString);

            // 3.构建扣减商品库存VO
            List<GoodsQuantityVO> quantityVOList = new ArrayList<>();
            for (OrderItemsDO orderItem : orderItems) {
                GoodsQuantityVO goodsQuantity = new GoodsQuantityVO();
                goodsQuantity.setGoodsId(orderItem.getGoodsId());
                //设置为要减掉的库存
                goodsQuantity.setQuantity(0 - orderItem.getNum());
                //发货要减少实际的库存
                goodsQuantity.setQuantityType(QuantityType.actual);
                goodsQuantity.setSkuId(orderItem.getProductId());
                quantityVOList.add(goodsQuantity);
            }
            // 4.扣减库存
            goodsQuantityClient.updateSkuQuantity(quantityVOList);

        }

        //付款前 订单取消++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        if (orderMessage.getNewStatus().name().equals(OrderStatusEnum.CANCELLED.name()) && orderMessage.getOrderDO().getPayStatus().equals(PayStatusEnum.PAY_NO.name())) {

            List<GoodsQuantityVO> quantityVOList = new ArrayList<>();

            OrderDO order = orderMessage.getOrderDO();
            String itemsJson = order.getItemsJson();
            List<OrderSkuVO> list = JsonUtil.jsonToList(itemsJson, OrderSkuVO.class);

            for (OrderSkuVO sku : list) {

                GoodsQuantityVO goodsQuantity = new GoodsQuantityVO();
                goodsQuantity.setGoodsId(sku.getGoodsId());

                //取消订单要恢复下单时占用的可用库存
                goodsQuantity.setQuantity(sku.getNum());
                goodsQuantity.setQuantityType(QuantityType.enable);
                goodsQuantity.setSkuId(sku.getSkuId());
                quantityVOList.add(goodsQuantity);

            }

            goodsQuantityClient.updateSkuQuantity(quantityVOList);
            // 回滚促销库存
            List<CartSkuVO> cartSkuVOS = JSON.parseArray(itemsJson,CartSkuVO.class);
            OrderDTO orderDTO = new OrderDTO();
            orderDTO.setSkuList(cartSkuVOS);
            orderDTO.setSn(order.getSn());
            goodsStockManager.rollbackPromotionStock(orderDTO);
        }

    }

    @Override
    public void refund(RefundChangeMsg refundChangeMsg) {
        RefundDO refund = refundChangeMsg.getRefund();
        //获取当前订单信息
        OrderDetailDTO orderDetailDTO = orderClient.getModel(refundChangeMsg.getRefund().getOrderSn());
        //退款 当商家审核已通过且未发货 增加可用库存
        boolean bool = refund.getRefuseType().equals(RefuseTypeEnum.RETURN_MONEY.name()) && orderDetailDTO.getShipStatus().equals(ShipStatusEnum.SHIP_NO.name()) && refundChangeMsg.getRefundStatusEnum().name().equals(RefundStatusEnum.PASS.name());
        List<RefundGoodsDO> goodsList = afterSaleClient.getRefundGoods(refund.getSn());
        if (bool) {

            List<GoodsQuantityVO> quantityVOList = new ArrayList<>();

            for (RefundGoodsDO goods : goodsList) {
                // 商品入库
                GoodsQuantityVO goodsQuantity = new GoodsQuantityVO();
                goodsQuantity.setSkuId(goods.getSkuId());
                goodsQuantity.setGoodsId(goods.getGoodsId());
                goodsQuantity.setQuantity(goods.getReturnNum());
                goodsQuantity.setQuantityType(QuantityType.enable);
                quantityVOList.add(goodsQuantity);
            }

            goodsQuantityClient.updateSkuQuantity(quantityVOList);

        }

        //退货且订单入库，增加库存
        bool = refund.getRefuseType().equals(RefuseTypeEnum.RETURN_GOODS.name()) && refundChangeMsg.getRefundStatusEnum().equals(RefundStatusEnum.STOCK_IN);
        if (bool) {

            List<GoodsQuantityVO> quantityVOList = new ArrayList<>();

            for (RefundGoodsDO goods : goodsList) {
                // 商品入库
                GoodsQuantityVO goodsQuantity = new GoodsQuantityVO();
                goodsQuantity.setSkuId(goods.getSkuId());
                goodsQuantity.setGoodsId(goods.getGoodsId());
                goodsQuantity.setQuantity(goods.getReturnNum());

                //先增加实际库存
                goodsQuantity.setQuantityType(QuantityType.actual);
                quantityVOList.add(goodsQuantity);
            }

            //先增加实际库存
            goodsQuantityClient.updateSkuQuantity(quantityVOList);

            quantityVOList.forEach(goodsQuantityVO -> {
                goodsQuantityVO.setQuantityType(QuantityType.enable);
            });
            //再增加可用库存
            goodsQuantityClient.updateSkuQuantity(quantityVOList);
        }
    }
}
